package cn.hehuoren.quartz.service.impl;

import cn.hehuoren.core.utils.StringUtil;
import cn.hehuoren.quartz.dao.QuartzManagerMapper;
import cn.hehuoren.quartz.model.QuartzManager;
import cn.hehuoren.quartz.service.IQuartzManagerService;
import cn.hehuoren.quartz.service.ISchedulerService;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import cn.hehuoren.core.exception.BusinessException;
import cn.hehuoren.core.utils.GridModel;
import cn.hehuoren.core.utils.SpringUtil;
import org.apache.ibatis.annotations.Param;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.UnableToInterruptJobException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

@Service
@com.alibaba.dubbo.config.annotation.Service
public class QuartzManagerServiceImpl implements IQuartzManagerService {
    public static final Logger logger = LoggerFactory.getLogger(QuartzManagerServiceImpl.class);
    
    public static final String DETAULF_JOB_FACTORY_CLASS_NAME = "cn.hehuoren.quartz.base.CommonJobBean";
	
    @Autowired
    QuartzManagerMapper quartzManagerMapper;
    
    @Autowired
    private ISchedulerService schedulerService;
    
    /**
     * 
     * @创建人 ZhouMin
     * @创建时间 2015年10月22日
     * @创建目的【检查保存的quartz信息，有错则抛异常.新增和修改job时用到】
     * @修改目的【修改人：，修改时间：】
     * @param quartzManager
     * @throws Exception
     */
    public void checkSaveQuartzInfo(QuartzManager quartzManager) throws ClassNotFoundException {
        Class clazz = Class.forName(quartzManager.getDtlJobClassName());
        if (!Job.class.isAssignableFrom(clazz)) {
            throw new BusinessException("新增失败：JobClass必须是Job类的实现类");
        }
        AutowireCapableBeanFactory beanfactory = SpringUtil.getApplicationContext().getAutowireCapableBeanFactory();
        String jobId = quartzManager.getDtlJobName();
        String serviceName = quartzManager.getJobDataMap().get("serviceName");
        if(StringUtil.isEmpty(serviceName))throw new BusinessException("新增失败：任务的调度服务名不存在");
        //这里有点问题 ，如果第二个字母也是大写的时候 spring是不会把第一个字母变小写的，所以要求在配置的时候要区分大小写
//        String invokeServiceName = StringUtil.camelName(serviceName);
        
        logger.info("添加job:{jobId}",jobId);
       // Object jobObject = beanfactory.containsBean(jobId);
        if(!beanfactory.containsBean(serviceName)){
            throw new BusinessException("新增失败：任务["+jobId+"]对应的服务名["+serviceName+"]不存在");
        }else{
            Object jobObject = beanfactory.getBean(serviceName);
            Class<? extends Object> jobClass = jobObject.getClass();
            Method[] methods = jobClass.getMethods();
            boolean hasMethod = false;
            for (Method method : methods) {
                String invokeMethod = quartzManager.getJobDataMap().get("method");
                if(this.equals(method.getName(), invokeMethod)){
                    hasMethod=true;
                    break;
                }
            }
            if(hasMethod==false){
                throw new BusinessException("新增失败：任务的调度方法不存在");
            }
        }
    }

    private boolean equals(String str1, String str2){
        return str1 == null ? str2 == null : str1.equals(str2);
    }
    /**
     * 
     * @创建人 ZhouMin
     * @创建时间 2016年3月22日
     * @创建目的【新增定时任务】
     * @修改目的【修改人：，修改时间：】
     * @param quartzManager
     */
    @Override
    public void addQuarzTask(QuartzManager quartzManager){
        Class clazz = null;
        try {
            if(StringUtil.isEmpty(quartzManager.getDtlJobClassName())){
                quartzManager.setDtlJobClassName(DETAULF_JOB_FACTORY_CLASS_NAME);
            }
            clazz = (Class)Class.forName(quartzManager.getDtlJobClassName());
            checkSaveQuartzInfo(quartzManager);
        } catch (Exception e) {
            logger.error("添加任务失败", e);
            throw new BusinessException(e.getMessage());
        }
       
        try {
            schedulerService.registScheduleJob(quartzManager, clazz);
        } catch (Exception e) {
            e.printStackTrace();
           throw new BusinessException(e.getMessage());
        }
    }
    
    /**
     * 
     * @创建人 ZhouMin
     * @创建时间 2016年3月22日
     * @创建目的【新增定时任务】
     * @修改目的【修改人：，修改时间：】
     * @param quartzManager
     */
    @Override
    public void updateQuarzTask(QuartzManager quartzManager){
        Class clazz = null;
        try {
            if(StringUtil.isEmpty(quartzManager.getDtlJobClassName())){
                quartzManager.setDtlJobClassName(DETAULF_JOB_FACTORY_CLASS_NAME);
            }
            clazz = (Class)Class.forName(quartzManager.getDtlJobClassName());
            checkSaveQuartzInfo(quartzManager);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new BusinessException(e.getMessage());
        }
       
        try {
            schedulerService.registScheduleJobUpdate(quartzManager, clazz);
        } catch (Exception e) {
            e.printStackTrace();
           throw new BusinessException(e.getMessage());
        }
    }
    //删除任务
    @Override
    public boolean deleteJob(QuartzManager quartzManager){
        try {
            return schedulerService.deleteJob(quartzManager);
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //暂停任务
    @Override
    public void pauseJob(QuartzManager quartzManager){
        try {
            schedulerService.pauseJob(quartzManager);
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //恢复任务
    @Override
    public void resumeJob(QuartzManager quartzManager){
        try {
            schedulerService.resumeJob(quartzManager);
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //中断任务
    @Override
    public boolean interrupt(QuartzManager quartzManager){
        try {
            return schedulerService.interrupt(quartzManager);
        } catch (UnableToInterruptJobException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //触发一次任务
    @Override
    public void triggerJob(QuartzManager quartzManager){
        try {
            schedulerService.triggerJob(quartzManager);
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //暂停所有任务
    @Override
    public void pauseJob(){
        try {
            schedulerService.pauseJob();
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    //停止调度器
    @Override
    public void shutdownScheduler(){
        try {
            schedulerService.shutdownScheduler();
        } catch (SchedulerException e) {
            throw new BusinessException("定时任务操作失败:" + e.getMessage());
        }
    }
    
	@Override
	public int getTotal(@Param("start") Integer start,
			@Param("num") Integer num,
			@Param("dtlSchedName") String dtlSchedName,
			@Param("dtlJobName") String dtlJobName,
			@Param("dtlJobGroup") String dtlJobGroup,
			@Param("dtlDescription") String dtlDescription) {
		return quartzManagerMapper.getTotal(dtlSchedName,
				dtlJobName, dtlJobGroup, dtlDescription);
	}

	@Override
	public int deleteQrtzJobDetails(QuartzManager quartzManager) {
		return quartzManagerMapper.deleteQrtzJobDetails(quartzManager);
	}

	@Override
	public int deleteQrtzTriggers(QuartzManager quartzManager) {
		return quartzManagerMapper.deleteQrtzTriggers(quartzManager);
	}

	@Override
	public int deleteQrtzCronTriggers(QuartzManager quartzManager) {
		return quartzManagerMapper.deleteQrtzCronTriggers(quartzManager);
	}

	@Override
	public QuartzManager getByKey(@Param("dtlSchedName") String dtlSchedName,
			@Param("dtlJobName") String dtlJobName,
			@Param("dtlJobGroup") String dtlJobGroup) {
	    QuartzManager quartzManager=  quartzManagerMapper.getByKey(dtlSchedName,dtlJobName, dtlJobGroup);
        try {
            JobDetail jobDetail= schedulerService.getJobDetailByKey(dtlJobName,dtlJobGroup);
            quartzManager.setJobDataMap(new HashMap(jobDetail.getJobDataMap()));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
	    return quartzManager;
	}

	@Override
	public List<QuartzManager> select(@Param("start") Integer start,
			@Param("num") Integer num,
			@Param("dtlSchedName") String dtlSchedName,
			@Param("dtlJobName") String dtlJobName,
			@Param("dtlJobGroup") String dtlJobGroup,
			@Param("dtlDescription") String dtlDescription) {
		return quartzManagerMapper.select(start, num, dtlSchedName, dtlJobName,
				dtlJobGroup, dtlDescription);
	}

	@Override
	public int runSingleTime(String trigTriggerName, String trigTriggerGroup) {
		return quartzManagerMapper.runSingleTime(trigTriggerName, trigTriggerGroup);
	}

	@Override
	public String checkJobIsComplete(String trigTriggerName,
			String trigTriggerGroup) {
		return quartzManagerMapper.checkJobIsComplete(trigTriggerName, trigTriggerGroup);
	}
	
	@Override
    public GridModel<QuartzManager> selectQuartzManagerPage(QuartzManager quartzManager, int pageNum, int pageSize, String orderStr){
        PageBounds pageBounds = new PageBounds(pageNum, pageSize , Order.formString(orderStr));
        PageList<QuartzManager> pageList = (PageList<QuartzManager>)quartzManagerMapper.selectQuartzManagerPage(quartzManager,pageBounds);
        return new GridModel<QuartzManager>(pageList);
	}

}
